﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GenericGA.extrandom;

namespace GenericGA.generationmaker.mutation
{
    /// <summary>
    /// A class for mutating a chromosome.
    /// </summary>
    public abstract class Mutation
    {

        /// <summary>
        /// Return a mask with only one bit set.
        /// </summary>
        /// <param name="i">The index of the bit to set.</param>
        /// <returns>A single bit mask.</returns>
        public static ulong SingleBitMask(int i)
        {
            return (ulong)Math.Pow(2, 64 - i - 1);
        }

        /// <summary>
        /// Return a mask with multiple bits set.
        /// </summary>
        /// <param name="indices">An array of indices of the bits to set.</param>
        /// <returns>A bit mask.</returns>
        public static ulong BitMask(int[] indices)
        {
            ulong mask = 0;
            foreach (int i in indices)
            {
                mask |= SingleBitMask(i);
            }
            return mask;
        }
        
        /// <summary>
        /// Flip the bits of an element of a chromosome according to a mask.
        /// </summary>
        /// <param name="l">The chromosome containing the original element to mutate.</param>
        /// <param name="i">The position of the element to mutate.</param>
        /// <param name="mask">The mask where set bits indicate that the corresponding bit in the chromosome is to be flipped.</param>
        public static void FlipBits(List<ulong> l, int i, ulong mask)
        {
            l[i] ^= mask;
        }

        /// <summary>
        /// Mutate the given chromosome by overwriting it.
        /// </summary>
        /// <param name="bits">The chromosome to mutate. Will be modified.</param>
        public abstract void Mutate(List<ulong> mutant);

    }
}
